using System;
using Gj;
using UnityEngine;
using Random = System.Random;

/// <summary>
///     命令枚举
/// </summary>
public enum AI_INFO
{
    // 基础
    Base,

    // 属性
    Attr
}

public enum AI_BASE_SELECT
{
    // 距离
    DISTANCE,
    NUMBER
}

public enum AI_COMMAND_FLAG
{
    // 执行一次
    OnlyOnce = 0,

    // 持续执行到目标发生变化
    HoldTarget = 1,

    // 执行一次，执行下个命令
    OnlyOnceContinue = 2,

    // 执行一次，执行上一个命令
    OnlyOnceReturn = 3
}

/// <summary>
///     AI调度器
/// </summary>
[RequireComponent(typeof(CommandPart))]
public class AiPart : BasePart, CommandPart.Notice
{
    private CommandPart _commandPart;
    private Random _random;
    private Ai _self;
    private AiSoul _soul;

    private int commandIndex = -1;
    private int mutx;

    public CommandPart CommandPart
    {
        get
        {
            if (_commandPart == null) _commandPart = GetComponent<CommandPart>();
            return _commandPart;
        }
    }

    /// <summary>
    ///     通知ai当前命令需要锁定
    /// </summary>
    void CommandPart.Notice.Lock()
    {
        var entity = _self.GetEntity();
        ObjectService.EntityManager.AddComponentData(entity, new AiLockStateData());
    }

    /// <summary>
    ///     通知ai当前命令解锁
    /// </summary>
    void CommandPart.Notice.UnLock()
    {
        var entity = _self.GetEntity();
        ObjectService.EntityManager.RemoveComponent<AiLockStateData>(entity);
    }

    /// <summary>
    ///     初始化
    /// </summary>
    public void Init(AiSoul soul, Ai ai)
    {
        _self = ai;
        _soul = soul;
        _random = new Random(Convert.ToInt32(ai.GetId()));

        CommandPart.Init(_self);
        CommandPart.Set(this);

        var entity = _self.GetEntity();
        ObjectService.EntityManager.AddComponentData(entity,
            new AiData { scanRadius = soul.model.scanRadius, maxIndex = soul.model.commands.Count - 1 });
        ObjectService.EntityManager.AddComponentData(entity, new AiSelectData { commandIndex = 0, filter = false });
        ObjectService.EntityManager.AddComponentData(entity, new AiLastCommandData { commandIndex = -1 });
        ObjectService.EntityManager.AddComponent<AiWaitGroupData>(entity);
        ObjectService.EntityManager.AddSharedComponentManaged(entity,
            new AiBrainStateData { state = AiBrainState.Wait });
    }

    public void Stop()
    {
        var entity = _self.GetEntity();
        ObjectService.EntityManager.RemoveComponent<AiData>(entity);
        ObjectService.EntityManager.RemoveComponent<AiGroupData>(entity);
    }

    public AiCommand GetCommand(int commandIndex)
    {
        return _soul.model.commands[commandIndex];
    }

    /// <summary>
    ///     执行命令
    /// </summary>
    /// <param name="aiCommand"></param>
    public void OnExecute(int commandIndex, Life target)
    {
        mutx++;
        if (mutx == 1)
            // 当前为第一次run，添加state
            ObjectService.EntityManager.AddComponentData(_self.GetEntity(), new AiRunStateData());
        else
            CommandPart.Cancel();

        this.commandIndex = commandIndex;
        var command = _soul.model.commands[commandIndex];
        command.executing = true;
        var aiCommand = (AI_COMMAND)command.command;
        Debug.LogErrorFormat("Command: {0}, {1}, {2}", _self.GetId(), aiCommand, mutx);
        // todo 切换模式
        switch (aiCommand)
        {
            case AI_COMMAND.TargetCast:
                Debug.LogErrorFormat("TargetCast: {0}, {1}", target.GetName(),
                    EngineService.single.GetSkill(command.relationId));
                TargetCast(target, EngineService.single.GetSkill(command.relationId));
                break;
            case AI_COMMAND.PositionCast:
                PositionCast(target.GetPosition(), EngineService.single.GetSkill(command.relationId));
                break;
            case AI_COMMAND.Escape:
                Escape();
                break;
            case AI_COMMAND.Help:
                Help(EngineService.single.GetSkill(command.relationId));
                break;
            case AI_COMMAND.Patrol:
                Patrol();
                break;
            case AI_COMMAND.Standby:
                Standby();
                break;
            case AI_COMMAND.Sos:
                Sos();
                break;
            case AI_COMMAND.Stroll:
                Stroll();
                break;
            case AI_COMMAND.Follow:
                Follow(target);
                break;
        }

        ObjectService.EntityManager.SetSharedComponentManaged(_self.GetEntity(),
            new AiBrainStateData { state = AiBrainState.Run });
    }


    /// <summary>
    ///     对目标释放技能
    /// </summary>
    /// <param name="info"></param>
    /// <param name="skill"></param>
    public void TargetCast(Life life, Skill skill)
    {
        if (life == null)
        {
            CastBack(CommandPart.ProcessResult.cancel);
            return;
        }

        CommandPart.MoveCastTarget(skill, life, CastBack);
    }

    public void PositionCast(Vector3 position, Skill skill)
    {
        CommandPart.MoveCastPosition(skill, position, CastBack);
    }

    /// <summary>
    ///     帮助目标
    /// </summary>
    /// <param name="target"></param>
    public void Help(Skill skill)
    {
//        Debug.Log("command Help");
    }

    /// <summary>
    ///     巡逻
    /// </summary>
    public void Patrol()
    {
//        Debug.Log("command Patrol");
    }

    /// <summary>
    ///     逃跑
    /// </summary>
    public void Escape()
    {
//        Debug.Log("command Escape");
    }

    /// <summary>
    ///     待命
    /// </summary>
    public void Standby()
    {
//        Debug.Log("command Standby");
    }

    /// <summary>
    ///     求救
    /// </summary>
    public void Sos()
    {
//        Debug.Log("command Sos");
    }

    /// <summary>
    ///     散步
    /// </summary>
    /// <param name="info"></param>
    public void Stroll()
    {
        var pos = _self.GetPosition() + Quaternion.Euler(0, _random.Next(0, 360), 0) * Vector3.right * 10;
        var result = TerrainService.single.FindPosition(_self.GetPosition(), pos);
        if (result == null)
        {
            CastBack(CommandPart.ProcessResult.cancel);
            return;
        }

        CommandPart.MovePosition(result[result.Length - 1], CastBack);
    }

    public void Follow(Life life)
    {
        CommandPart.MoveTarget(life, CastBack);
    }

    private void CastBack(CommandPart.ProcessResult result)
    {
//        Debug.LogErrorFormat("CastBack: {0}", result);
        switch (result)
        {
            case CommandPart.ProcessResult.error:
                Error();
                break;
            case CommandPart.ProcessResult.cancel:
                Cancel(0);
                break;
            case CommandPart.ProcessResult.doing:
            case CommandPart.ProcessResult.success:
            default:
                // todo 是否可以end？
                End(0);
                break;
        }
    }

    public void OnRefresh()
    {
        CommandPart.Refresh();
    }


    /// <summary>
    ///     通知ai当前命令执行结束
    /// </summary>
    /// <param name="time"></param>
    private void End(float time)
    {
        _soul.model.commands[commandIndex].executing = false;
        ReleaseRun();
    }

    /// <summary>
    ///     通知ai当前命令执行中断
    /// </summary>
    /// <param name="time"></param>
    private void Cancel(float time)
    {
        _soul.model.commands[commandIndex].executing = false;
        ReleaseRun();
    }

    /// <summary>
    ///     通知ai当前命令错误
    /// </summary>
    private void Error()
    {
        _soul.model.commands[commandIndex].isError = true;
        _soul.model.commands[commandIndex].executing = false;
        ReleaseRun();
    }

    private void ReleaseRun()
    {
        mutx--;
        if (mutx == 0)
        {
            var entity = _self.GetEntity();
            ObjectService.EntityManager.RemoveComponent<AiRunStateData>(entity);
        }
    }
}